package com.ssy.lingxi.order.serviceimpl.web;

import cn.hutool.core.collection.CollUtil;
import com.ssy.lingxi.common.constant.basic.EnableDisableStatus;
import com.ssy.lingxi.common.exception.BusinessException;
import com.ssy.lingxi.common.model.dto.UserLoginCacheDTO;
import com.ssy.lingxi.common.response.Wrapper;
import com.ssy.lingxi.order.entity.BaseOrderTimeParamDO;
import com.ssy.lingxi.order.model.constant.OrderTimeParamEnum;
import com.ssy.lingxi.order.model.vo.basic.request.OrderDayParamVO;
import com.ssy.lingxi.order.model.vo.basic.request.OrderDeliveryTimeVO;
import com.ssy.lingxi.order.model.vo.basic.request.OrderShopIdVO;
import com.ssy.lingxi.order.model.vo.basic.response.DeliveryTimeVO;
import com.ssy.lingxi.order.model.vo.basic.response.OrderDayVO;
import com.ssy.lingxi.order.model.vo.basic.response.OrderDeliveryDateVO;
import com.ssy.lingxi.order.model.vo.basic.response.OrderTimeVO;
import com.ssy.lingxi.order.repository.BaseOrderTimeParamRepository;
import com.ssy.lingxi.order.service.base.IBaseCacheService;
import com.ssy.lingxi.order.service.web.IOrderTimeParamService;
import org.springframework.http.HttpHeaders;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @menu 系统能力 - 订单时间参数配置相关实现
 * @author wyx
 * @version 2.0.0
 * @date 2021-10-13
 */
@Service
public class OrderTimeParamServiceImpl implements IOrderTimeParamService {
    @Resource
    private IBaseCacheService baseCacheService;
    @Resource
    private BaseOrderTimeParamRepository orderTimeParamRepository;


    /**
     * 查看自动确认收货时间
     * @param headers HttpHeaders信息
     * @return 查询结果
     */
    @Override
    public Wrapper<List<OrderDayVO>> getReceiverDay(HttpHeaders headers) {
        UserLoginCacheDTO loginUser = baseCacheService.needLoginFromBusinessPlatform(headers);
        List<BaseOrderTimeParamDO> timeParamDOList = orderTimeParamRepository.findAllByMemberIdAndMemberRoleIdAndParamType(loginUser.getMemberId(), loginUser.getMemberRoleId(), OrderTimeParamEnum.AUTO_RECEIVE_DAY.getCode());

        List<OrderDayVO> orderDayVOS = timeParamDOList.stream().map(orderTime -> new OrderDayVO(orderTime.getStatus(), orderTime.getShopId(), orderTime.getDays())).collect(Collectors.toList());
        return Wrapper.success(orderDayVOS);
    }

    /**
     * 添加/修改自动确认收货时间
     * @param headers  HttpHeaders信息
     * @param updateVO 接口参数
     * @return 修改结果
     */
    @Transactional(rollbackFor = BusinessException.class)
    @Override
    public Wrapper<Void> updateReceiverDay(HttpHeaders headers, List<OrderDayParamVO> updateVO) {
        UserLoginCacheDTO loginUser = baseCacheService.needLoginFromBusinessPlatform(headers);
        orderTimeParamRepository.deleteAllByMemberIdAndMemberRoleIdAndParamType(loginUser.getMemberId(), loginUser.getMemberRoleId(), OrderTimeParamEnum.AUTO_RECEIVE_DAY.getCode());

        List<BaseOrderTimeParamDO> paramList = updateVO.stream().map(paramVO -> {
            BaseOrderTimeParamDO timeParamDO = new BaseOrderTimeParamDO();
            timeParamDO.setMemberId(loginUser.getMemberId());
            timeParamDO.setMemberRoleId(loginUser.getMemberRoleId());
            timeParamDO.setShopId(paramVO.getShopId());
            timeParamDO.setDays(paramVO.getDays());
            timeParamDO.setStatus(paramVO.getStatus());
            timeParamDO.setParamType(OrderTimeParamEnum.AUTO_RECEIVE_DAY.getCode());
            timeParamDO.setStartTime("");
            timeParamDO.setEndTime("");
            return timeParamDO;
        }).collect(Collectors.toList());

        orderTimeParamRepository.saveAll(paramList);
        return Wrapper.success();
    }

    /**
     * 查看送货预约时长
     * @param headers HttpHeaders信息
     * @return 查询结果
     */
    @Override
    public Wrapper<List<OrderDayVO>> getAppointmentDay(HttpHeaders headers) {
        UserLoginCacheDTO loginUser = baseCacheService.needLoginFromBusinessPlatform(headers);
        List<BaseOrderTimeParamDO> timeParamDOList = orderTimeParamRepository.findAllByMemberIdAndMemberRoleIdAndParamType(loginUser.getMemberId(), loginUser.getMemberRoleId(), OrderTimeParamEnum.DELIVERY_APPOINTMENT_DAY.getCode());

        List<OrderDayVO> orderDayVOS = timeParamDOList.stream().map(orderTime -> new OrderDayVO(orderTime.getStatus(), orderTime.getShopId(), orderTime.getDays())).collect(Collectors.toList());
        return Wrapper.success(orderDayVOS);
    }

    /**
     * 添加/修改送货预约时长
     * @param headers  HttpHeaders信息
     * @param updateVO 接口参数
     * @return 修改结果
     */
    @Transactional(rollbackFor = BusinessException.class)
    @Override
    public Wrapper<Void> updateAppointmentDay(HttpHeaders headers, List<OrderDayParamVO> updateVO) {
        UserLoginCacheDTO loginUser = baseCacheService.needLoginFromBusinessPlatform(headers);
        orderTimeParamRepository.deleteAllByMemberIdAndMemberRoleIdAndParamType(loginUser.getMemberId(), loginUser.getMemberRoleId(), OrderTimeParamEnum.DELIVERY_APPOINTMENT_DAY.getCode());

        List<BaseOrderTimeParamDO> paramList = updateVO.stream().map(paramVO -> {
            BaseOrderTimeParamDO timeParamDO = new BaseOrderTimeParamDO();
            timeParamDO.setMemberId(loginUser.getMemberId());
            timeParamDO.setMemberRoleId(loginUser.getMemberRoleId());
            timeParamDO.setShopId(paramVO.getShopId());
            timeParamDO.setDays(paramVO.getDays());
            timeParamDO.setStatus(paramVO.getStatus());
            timeParamDO.setParamType(OrderTimeParamEnum.DELIVERY_APPOINTMENT_DAY.getCode());
            timeParamDO.setStartTime("");
            timeParamDO.setEndTime("");
            return timeParamDO;
        }).collect(Collectors.toList());

        orderTimeParamRepository.saveAll(paramList);
        return Wrapper.success();
    }

    /**
     * 查看配置配送时间段
     * @param headers HttpHeaders信息
     * @return 查询结果
     */
    @Override
    public Wrapper<List<OrderTimeVO>> getDeliveryTime(HttpHeaders headers) {
        UserLoginCacheDTO loginUser = baseCacheService.needLoginFromBusinessPlatform(headers);
        List<BaseOrderTimeParamDO> timeParamDOList = orderTimeParamRepository.findAllByMemberIdAndMemberRoleIdAndParamType(loginUser.getMemberId(), loginUser.getMemberRoleId(), OrderTimeParamEnum.DELIVERY_TIME.getCode());

        //根据商城id分组
        Map<Long, List<BaseOrderTimeParamDO>> orderTimeMap = timeParamDOList.stream().collect(Collectors.groupingBy(BaseOrderTimeParamDO::getShopId));

        List<OrderTimeVO> orderTimeList = orderTimeMap.entrySet().stream().map(orderTime -> {
            List<BaseOrderTimeParamDO> timeList = orderTime.getValue();
            OrderTimeVO vo = new OrderTimeVO();
            vo.setShopId(orderTime.getKey());
            vo.setStatus(timeList.stream().findFirst().orElse(new BaseOrderTimeParamDO()).getStatus());
            vo.setParamList(timeList.stream().map(time -> new DeliveryTimeVO(time.getStartTime(), time.getEndTime())).sorted(Comparator.comparing(DeliveryTimeVO::getStartTime, Comparator.nullsLast(String::compareTo))).collect(Collectors.toList()));
            return vo;
        }).collect(Collectors.toList());

        return Wrapper.success(orderTimeList);
    }

    /**
     * 添加/修改配置配送时间段
     * @param headers  HttpHeaders信息
     * @param updateVO 接口参数
     * @return 修改结果
     */
    @Transactional(rollbackFor = BusinessException.class)
    @Override
    public Wrapper<Void> updateDeliveryTime(HttpHeaders headers, List<OrderDeliveryTimeVO> updateVO) {
        UserLoginCacheDTO loginUser = baseCacheService.needLoginFromBusinessPlatform(headers);
        orderTimeParamRepository.deleteAllByMemberIdAndMemberRoleIdAndParamType(loginUser.getMemberId(), loginUser.getMemberRoleId(), OrderTimeParamEnum.DELIVERY_TIME.getCode());

        //配送时间段参数
        List<BaseOrderTimeParamDO> paramList = updateVO.stream().flatMap(paramVO ->
                paramVO.getParamList().stream().map(timeVO -> {
                    BaseOrderTimeParamDO timeParamDO = new BaseOrderTimeParamDO();
                    timeParamDO.setMemberId(loginUser.getMemberId());
                    timeParamDO.setMemberRoleId(loginUser.getMemberRoleId());
                    timeParamDO.setShopId(paramVO.getShopId());
                    timeParamDO.setStatus(paramVO.getStatus());
                    timeParamDO.setStartTime(timeVO.getStartTime());
                    timeParamDO.setEndTime(timeVO.getEndTime());
                    timeParamDO.setParamType(OrderTimeParamEnum.DELIVERY_TIME.getCode());
                    return timeParamDO;
                })).collect(Collectors.toList());

        orderTimeParamRepository.saveAll(paramList);
        return Wrapper.success();
    }

    /**
     * 根据会员信息和商城id获取预约时长和配置配送时间段
     * @param headers HttpHeaders信息
     * @param shopIdVO 接口参数
     * @return 查询结果
     */
    @Override
    public Wrapper<OrderDeliveryDateVO> findDeliveryDate(HttpHeaders headers, OrderShopIdVO shopIdVO) {
        UserLoginCacheDTO loginUser = baseCacheService.needLoginFromBusinessPlatform(headers);

        //配置的时间参数
        List<BaseOrderTimeParamDO> timeParamList = orderTimeParamRepository.findAllByMemberIdAndMemberRoleIdAndShopIdAndStatus(loginUser.getMemberId(), loginUser.getMemberRoleId(), shopIdVO.getShopId(), EnableDisableStatus.ENABLE.getCode());
        OrderDeliveryDateVO vo = new OrderDeliveryDateVO();

        //送货预约时长
        BaseOrderTimeParamDO dayParam = timeParamList.stream().filter(dateParam -> OrderTimeParamEnum.DELIVERY_APPOINTMENT_DAY.getCode().equals(dateParam.getParamType())).findFirst().orElse(null);
        if (dayParam != null) {
            vo.setAppointmentDay(true);
            vo.setDays(dayParam.getDays());
        }

        //配送时间段
        List<DeliveryTimeVO> timeParam = timeParamList.stream().filter(dateParam -> OrderTimeParamEnum.DELIVERY_TIME.getCode().equals(dateParam.getParamType()))
                .map(time -> new DeliveryTimeVO(time.getStartTime(), time.getEndTime())).sorted(Comparator.comparing(DeliveryTimeVO::getStartTime, Comparator.nullsLast(String::compareTo))).collect(Collectors.toList());
        if (CollUtil.isNotEmpty(timeParam)) {
            vo.setDeliveryTime(true);
            vo.setParamList(timeParam);
        }

        return Wrapper.success(vo);
    }

    /**
     * 根据供应商会员信息和商城id获取预约时长和配置配送时间段
     * @param vendorMemberId 供应商会员id
     * @param vendorRoleId   供应商会员角色id
     * @param shopId         商城id
     * @return 查询结果
     */
    @Override
    public Wrapper<OrderDeliveryDateVO> findBuyerDeliveryDate(Long vendorMemberId, Long vendorRoleId, Long shopId) {
        //配置的时间参数
        List<BaseOrderTimeParamDO> timeParamList = orderTimeParamRepository.findAllByMemberIdAndMemberRoleIdAndShopIdAndStatus(vendorMemberId, vendorRoleId, shopId, EnableDisableStatus.ENABLE.getCode());
        OrderDeliveryDateVO vo = new OrderDeliveryDateVO();

        //送货预约时长
        BaseOrderTimeParamDO dayParam = timeParamList.stream().filter(dateParam -> OrderTimeParamEnum.DELIVERY_APPOINTMENT_DAY.getCode().equals(dateParam.getParamType())).findFirst().orElse(null);
        if (dayParam != null) {
            vo.setAppointmentDay(true);
            vo.setDays(dayParam.getDays());
        }

        //配送时间段
        List<DeliveryTimeVO> timeParam = timeParamList.stream().filter(dateParam -> OrderTimeParamEnum.DELIVERY_TIME.getCode().equals(dateParam.getParamType()))
                .map(time -> new DeliveryTimeVO(time.getStartTime(), time.getEndTime())).sorted(Comparator.comparing(DeliveryTimeVO::getStartTime, Comparator.nullsLast(String::compareTo))).collect(Collectors.toList());
        if (CollUtil.isNotEmpty(timeParam)) {
            vo.setDeliveryTime(true);
            vo.setParamList(timeParam);
        }

        return Wrapper.success(vo);
    }

    /**
     * 查询自动确认收货时间
     *
     * @param vendorMemberId 供应商会员Id
     * @param vendorRoleId   供应商会员角色Id
     * @param shopId         订单来源商城Id
     * @return 自动确认收货天数（如无配置返回0）
     */
    @Override
    public Integer getReceiveDays(Long vendorMemberId, Long vendorRoleId, Long shopId) {
        BaseOrderTimeParamDO receiveDays = orderTimeParamRepository.findFirstByMemberIdAndMemberRoleIdAndShopIdAndParamTypeAndStatus(vendorMemberId, vendorRoleId, shopId, OrderTimeParamEnum.AUTO_RECEIVE_DAY.getCode(), EnableDisableStatus.ENABLE.getCode());
        return receiveDays == null ? 0 : receiveDays.getDays();
    }
}
